/*
 * @lc app=leetcode.cn id=591 lang=cpp
 *
 * [591] 标签验证器
 */

// @lc code=start
class Solution
{
public:
    bool isValidTagName(string tagName)
    {
        int n = tagName.size();
        if (n < 1 || n > 9)
            return false;
        for (int i = 0; i < n; i++)
        {
            if (tagName[i] < 'A' || tagName[i] > 'Z')
                return false;
        }
        return true;
    }
    bool isValid(string code)
    {
        int n = code.size(), i = 0;
        stack<string> st;
        while (i < n)
        {
            if (code[i] == '<')
            {
                if (i + 1 == n)
                    return false;
                if (code[i + 1] == '/')
                {
                    if (st.empty())
                        return false;
                    string tagName = "";
                    i += 2;
                    while (i < n && code[i] != '>')
                    {
                        tagName += code[i];
                        i++;
                    }
                    if (tagName != st.top())
                        return false;
                    st.pop();
                    i++;
                    if (st.empty() && i != n)
                        return false;
                }
                else if (code[i + 1] == '!')
                {
                    if (st.empty())
                        return false;
                    string cdata = code.substr(i, 9);
                    if (cdata != "<![CDATA[")
                        return false;
                    int j = code.find("]]>", i);
                    if (j == string::npos)
                        return false;
                    i = j + 1;
                }
                else
                {
                    string tagName;
                    i++;
                    while (i < n && code[i] != '>')
                    {
                        tagName += code[i];
                        i++;
                    }
                    if (!isValidTagName(tagName))
                        return false;
                    st.push(tagName);
                    i++;
                }
            }
            else
            {
                if (st.empty())
                    return false;
                i++;
            }
        }
        return st.empty();
    }
};
// @lc code=end
